/******************************************************************************
 *  Include Files
 *****************************************************************************/
#include "NVM.h"
#include "DRV_FLASH.h"
#include "DSM.h"

/******************************************************************************
 *  Macro Definitions
 *****************************************************************************/

/******************************************************************************
 *  Const Definitions
 *****************************************************************************/

/*****************************************************************************
 *  Global Variables Definitions
 *****************************************************************************/
static uint32_t NVM_EEP_No[2] = {0};
static uint8_t NVM_EEP_CheckSum_OK[2] = {0};
static uint8_t NVM_EEP_ReadFlag = 0;

NVM NVM_EEP = {.No = 0,
               .Var1 = 0,
               .Var2 = 0,
               .Var3 = 0,
               .CheckSum = 0};

static DSM_DFC NVM_stErrInit = {.nNo_C = 0,
                                .stAdded_DFC_List = 0,
                                .stFault = {0},
                                .stFaultState = 80,
                                .cntrDeb = 0,
                                .cntrDebMax_C = 1,
                                .stFault_Type_C = DSM_FaultType_IRRV,
                                .stFault_ErrReactn_C = DSM_ErrReactn_CTRL_Stop};

/*****************************************************************************
 *  Local Function declarations
 *****************************************************************************/
uint32_t NVM_Check_CheckSum(uint32_t Addr, uint16_t Len);

/*****************************************************************************
 *  Function Definitions
 *****************************************************************************/
void NVM_Init(void) { NVM_ReadParam(); }

void NVM_ReadParam(void) {
  uint8_t i;
  NVM eep;
  for (i = 0; i < 2; i++) {
    DRV_FLASH_Read(NVM_EEP0_Adress + SECTOR_SIZE * i, &eep, sizeof(eep));
    NVM_EEP_No[i] = eep.No;
    if (NVM_Check_CheckSum((uint32_t)&eep, sizeof(eep) - 4) == eep.CheckSum) {
      NVM_EEP_CheckSum_OK[i] = 1;
    } else {
      NVM_EEP_CheckSum_OK[i] = 0;
    }
  }

  if ((1 == NVM_EEP_CheckSum_OK[0]) && (1 == NVM_EEP_CheckSum_OK[1])) {
    if (NVM_EEP_No[0] < NVM_EEP_No[1]) {
      DRV_FLASH_Read(NVM_EEP1_Adress, &NVM_EEP, sizeof(NVM_EEP));
      NVM_EEP_ReadFlag = 1;
    } else {
      DRV_FLASH_Read(NVM_EEP0_Adress, &NVM_EEP, sizeof(NVM_EEP));
      NVM_EEP_ReadFlag = 0;
    }
  } else if (1 == NVM_EEP_CheckSum_OK[0]) {
    DRV_FLASH_Read(NVM_EEP0_Adress, &NVM_EEP, sizeof(NVM_EEP));
    NVM_EEP_ReadFlag = 0;
  } else if (1 == NVM_EEP_CheckSum_OK[1]) {
    DRV_FLASH_Read(NVM_EEP1_Adress, &NVM_EEP, sizeof(NVM_EEP));
    NVM_EEP_ReadFlag = 1;
  } else {
    DSM_Trigger(&NVM_stErrInit, 0);
  }
}

void NVM_WriteParam(void) {
  NVM_EEP.No++;
  NVM_EEP.CheckSum =
      NVM_Check_CheckSum((uint32_t)&NVM_EEP, sizeof(NVM_EEP) - 4);

  if (0 == NVM_EEP_ReadFlag) {
    DRV_FLASH_Erase(NVM_EEP1_Adress, FLASH1_FLASH_ERASABLE_UNIT_SIZE);
    DRV_FLASH_Write(&NVM_EEP, NVM_EEP1_Adress, sizeof(NVM_EEP));
  } else {
    DRV_FLASH_Erase(NVM_EEP0_Adress, FLASH1_FLASH_ERASABLE_UNIT_SIZE);
    DRV_FLASH_Write(&NVM_EEP, NVM_EEP0_Adress, sizeof(NVM_EEP));
  }
}

uint32_t NVM_Check_CheckSum(uint32_t Addr, uint16_t Len) {
  uint32_t i = 0, chks = 0;
  for (i = Addr; i < Addr + Len; i++) {
    chks += *(uint8_t *)i;
    chks++;
  }
  return chks;
}
